package utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;


/**
 * 图片工具
 */
public class ImageUtil {

    /**
     * 压缩图片
     *
     * @param source
     * @return
     */
    private static BufferedImage img;
    private static int width;
    private static int height;
    private static int RATIO = 2;

    /**
     * 设置流对象
     */
    public static void setInput(InputStream in) throws IOException {
        img = ImageIO.read(in);      // 构造Image对象
        width = img.getWidth(null);    // 得到源图宽
        height = img.getHeight(null);  // 得到源图长
    }


    /**
     * 读取网络图片
     *
     * @param destUrl
     * @return
     * @throws IOException
     */
    public static InputStream inputFromUrl(String destUrl) throws IOException {
        if (urlEmpty(destUrl)) {
            throw new IOException("url不能为空");
        }
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        HttpURLConnection httpUrl = null;
        URL url;
        try {
            url = new URL(destUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            return httpUrl.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
                bis.close();
                httpUrl.disconnect();
            } catch (IOException e) {
            } catch (NullPointerException e) {
            }
        }
        return null;
    }

    /**
     * 按照宽度还是高度进行压缩
     *
     * @param w int 最大宽度
     * @param h int 最大高度
     */
    public static ByteArrayOutputStream resizeFix(int w, int h) throws IOException {
        if (width / height > w / h) {
            return resizeByWidth(w);
        } else {
            return resizeByHeight(h);
        }
    }

    /**
     * 以宽度为基准，等比例放缩图片
     *
     * @param w int 新宽度
     */
    public static ByteArrayOutputStream resizeByWidth(int w) throws IOException {
        int h = (int) (height * w / width);
        return resize(w, h);
    }

    /**
     * 以高度为基准，等比例缩放图片
     *
     * @param h int 新高度
     */
    public static ByteArrayOutputStream resizeByHeight(int h) throws IOException {
        int w = (int) (width * h / height);
        return resize(w, h);
    }


    /**
     * 强制压缩/放大图片到固定的大小
     *
     * @param w int 新宽度
     * @param h int 新高度
     */
    private static ByteArrayOutputStream resize(int w, int h) throws IOException {
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        image.getGraphics().drawImage(img, 0, 0, w, h, null);
        ImageWriter imgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        imgWriter.setOutput(ImageIO.createImageOutputStream(out));
        imgWriter.write(null, new IIOImage(image, null, null), null);
        return out;
    }


    /**
     * 通过图片URL来压缩，生成指定路径的图片
     *
     * @param url
     * @param descFilePath
     * @return
     * @throws IOException
     */
    public static boolean compressFromUrl(String url, String descFilePath) throws IOException {
        if (urlEmpty(url)) {
            throw new IOException("url不能为空");
        }
        InputStream in = inputFromUrl(url);
        return compress2Path(in, descFilePath);
    }


    public static ByteArrayOutputStream compress2Byte(InputStream in) throws IOException {
        if (inputEmpty(in)) {
            throw new IOException("inputStream不能为空");
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ByteArrayOutputStream compress = (ByteArrayOutputStream) compress(in, out);
            return compress;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 设置压缩比率，整数 传 0 为不压缩
     *
     * @param ratio
     */
    public static void setCompressRatio(int ratio) {
        RATIO = ratio;
    }

    /**
     * 压缩到本地
     *
     * @param in
     * @param descPath
     * @return
     */
    public static boolean compress2Path(InputStream in, String descPath) throws IOException {
        if (inputEmpty(in)) {
            throw new IOException("input 不能为空");
        }
        FileOutputStream out;
        OutputStream compress;
        try {
            out = new FileOutputStream(descPath);
            compress = compress(in, out);
            compress.close();
            out.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成压缩后的输出字节流
     *
     * @param in
     * @param out
     * @return
     * @throws IOException
     */
    public static OutputStream compress(InputStream in, OutputStream out) throws IOException {
        ImageWriter imgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
        ImageWriteParam imgWriteParams = new javax.imageio.plugins.jpeg.JPEGImageWriteParam(null);
        imgWriteParams.setCompressionMode(imgWriteParams.MODE_EXPLICIT);
        if (RATIO == 0) {
            RATIO = 1;
        }
        imgWriteParams.setCompressionQuality((float) 1 / RATIO);
        imgWriteParams.setProgressiveMode(imgWriteParams.MODE_DISABLED);
        BufferedImage image = ImageIO.read(in);
        ColorModel colorModel = image.getColorModel();
        // ColorModel.getRGBdefault();
        imgWriteParams.setDestinationType(new javax.imageio.ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16)));
        imgWriter.reset();
        imgWriter.setOutput(ImageIO.createImageOutputStream(out));
        imgWriter.write(null, new IIOImage(image, null, null), imgWriteParams);
        return out;
    }

    /**
     * @param imgStr base64编码字符串
     * @param path   图片路径-具体到文件
     * @return
     * @Description: 将base64编码字符串转换为图片
     * @Author:
     * @CreateTime:
     */
    public static boolean generateImage(String imgStr, String path) {

        String base64Pic = "";
        String picName = "";

        if (imgStr == null) {
            return false;
        }
        String imgStrs = imgStr.replaceAll("data:image/png;base64,", "");
        BASE64Decoder decoder = new BASE64Decoder();
        // Base64解码
        byte[] imageByte = null;
        try {
            imageByte = decoder.decodeBuffer(imgStrs);
            for (int i = 0; i < imageByte.length; ++i) {
                if (imageByte[i] < 0) {// 调整异常数据
                    imageByte[i] += 256;
                }
            }

        OutputStream out = new FileOutputStream(path);
            out.write(imageByte);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * @Description: 根据图片地址转换为base64编码字符串
     * @Author:
     * @CreateTime:
     * @return
     */
    public static String getImageStr(String imgFile) {
        InputStream inputStream = null;
        byte[] data = null;
        try {
            inputStream = new FileInputStream(imgFile);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 加密
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    private static boolean urlEmpty(String url) {
        return null == url || "".equals(url);
    }

    private static boolean inputEmpty(InputStream inputStream) {
        return null == inputStream;
    }

}
